#ifndef _SPRITE_H_
#define _SPRITE_H_

#include "v-graphs.h"
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include "pixmap.h"
#include "utypes.h"
#include "game.h"
#include <conio.h>

/** @defgroup Sprite Sprite
 * @{
 *
 * Sprite related functions
 */

#define BACK BLACK ///< color of background

extern Bool saida_sprite;  ///< boolean to define sprite leave
extern Bool chegada_sprite;///< boolean to define sprite arrival
extern int xini;	///< initial x coordinate of the player_sprite when it starts to paint
extern int yini;    ///< initial y coordinate of the player_sprite when it starts to paint

/** A Sprite is an "object" that contains all needed information to
 * create, animate, and destroy a pixmap.  The functions assume that
 * the background is BLACK and they take into account collision with
 * other graphical objects or the screen limits. 
 */
typedef struct {
  int x;			///< current x sprite position
  int y;            ///< current y sprite position
  int width;		///< sprite width
  int height;		///< sprite height
  int xspeed;		///< sprite current xspeed
  int yspeed;		///< sprite current yspeed
  char *map;        ///< the sprite pixmap (use read_xpm())
} Sprite;

/** A Player_Sprite is an "object" that contains all needed information to
 * create, animate, and destroy a pixmap.  The functions assume that
 * the background is BLACK and they take into account collision with
 * other graphical objects or the screen limits. Dosn't have speed, because it's animated by player
 */
typedef struct {
	int x;				///< current x sprite position
	int y;				///< current y sprite position
	int width;			///< sprite width
	int height;			///< sprite height
	char *map;			///< the sprite pixmap (use read_xpm())
	char *bgmap;		///< the sprite back's pixmap (use read_xpm())
} Player_Sprite;


#define MAX_SPEED 5    /**< each sprite maximum speed in pixels/frame */
#define RIGHT_HIT 2    /**< collision with right block (WHITE)  */
#define LEFT_HIT 3     /**< collision with left block (WHITE)   */
#define MOUSE_HIT 4    /**< collision with mouse (LIGHTMAGENTA) */


/** Reads a xpm-like sprite defined in "map" (look at pixmap.h for
 * examples). Returns the address of the allocated memory where the
 * sprite was read. Updates "width" and "heigh" with the sprite
 * dimension.  Return NULL on error.
 * Assumes that VRES and HRES (the screen vertical and horizontal resolution)
 * are externaly defined.
 * 
 * Usage example, using the defined sprite in pixmap.h:
 * <pre>
 *   include "pixmap.h" // defines  pic1, pic2, etc 
 *   int wd, hg;
 *   char *sprite = read_xpm(pic1, &wd, &hg);
 * </pre>
*/
char *read_xpm(char *map[], int *width, int *height);

/** Creates with random speeds (not zero) and position
 * (within the screen limits), a new sprite with pixmap "pic", in
 * memory whose address is "base".
 * Returns NULL on invalid pixmap.
 */
Sprite * create_sprite(char *pic[], char *base,int x, int y);

/** Creates with random speeds (not zero) and position
 * (within the screen limits), a new Player_Sprite with pixmap "pic", in
 * memory whose address is "base".
 * Returns NULL on invalid pixmap.
 */
Player_Sprite * create_player_sprite(char *pic[],char * base, int x, int y);

/** Draws the sprite
*/
void draw_sprite(Sprite * sprt,char *base);

/** Draws the Player_Sprite
*/
void draw_player_sprite(Player_Sprite *sprt,char *base);

/** Animate the sprite "fig" according to its attributes in memory, 
 * whose address is "base".
 * The animation detects the screen borders
 * and change the speed according; it also detects collision with
 * other objects, including the player pad. Collisions with the screen
 * border generates a perfect reflection, while collision with other
 * objects generates a random perturbation in the object speed. Other
 * strategies can be devised: use quasi-elastic collision based on the
 * objects "mass" and speed, generate spin effect based on amount of
 * tangential speed direction relative to the object center of
 * "mass"...  Returns the kind of collision detected, RIGHT_HIT or
 * LEFT_HIT, if a collision with the players pad (WHITE colored!) is
 * detected.
 */
int animate_sprite(Sprite *fig, char *base);

/** The "fig" sprite is erased from memory whose address is "base"
 * and used resources released.
 */
void destroy_sprite(Sprite *fig, char *base);

/** The "sprt" Player_Sprite is erased from memory whose address is "base"
 * and used resources released.
 */
void destroy_player_sprite(Player_Sprite *sprt, char *base);

/** Cleans the Sprite from memory whose address is "base", drawing a black square at it position
 */
void clean_screen_sprite(Sprite *sprt, char *base);

/** Cleans the Player_Sprite from memory whose address is "base", drawing a black square at it position
 */
void clean_screen_player_sprite(Player_Sprite *sprt, char *base);

/** Animate the Player_Sprite "fig" according to its attributes in memory, 
 * whose address is "base".
 * The animation detects the screen borders
 * and change the speed according; it also detects collision with
 * other objects. Collisions with the screen
 * border generates a perfect reflection, while collision with other
 * objects generates a random perturbation in the object speed. Other
 * strategies can be devised: use quasi-elastic collision based on the
 * objects "mass" and speed, generate spin effect based on amount of
 * tangential speed direction relative to the object center of
 * "mass"...  Returns the kind of collision detected, RIGHT_HIT or
 * LEFT_HIT.
 */
int move_player_sprite(Player_Sprite * fig, char* base, int x, int y, char flag);

/** Draw a Rectangle starting at (x, y) with colour "colour", height*width, filled or not from memory whose address is "base"
 */
void drawRectangle(int x, int y, int colour, int height, int width, Bool filled, char* base);

/** Checks if the right side of the sprite if coliding with some object, by iteranting over the param hg
 */
Bool direita_livre(int xf, int yf,int hg,int wd, char* base);

/** Checks if the left side of the sprite if coliding with some object, by iteranting over the param hg
 */
Bool esquerda_livre(int xf, int yf,int hg, char* base);

/** Checks if the up side of the sprite if coliding with some object, by iteranting over the param wd
 */
Bool cima_livre(int xf, int yf,int wd, char* base);

/** Checks if the right side of the sprite if coliding with some object, by iteranting over the param wd
 */
Bool baixo_livre(int xf, int yf, int hg,int wd,char* base);

/** Leaves trail for Player_Sprite "sprt" to paint the screen
 */
void leave_trail(Player_Sprite *sprt, char *base);

/** Checks if the sprite has left the border
 */
Bool saida(int xf,int yf,int hg, int wd, char* base);

/** Checks if the sprite has arrived to the border
 */
Bool chegada(int xf,int yf,int hg, int wd, char* base);

/** Algorithm to fill region with visible border with color "BORDER_COLOR"
 *(Boundary Analisys Algorithm)
 */
void fillRegion(int xi, int yi, char* base);

/** Checks if the sprite has colided
 */
int check_colision(Sprite *fig, char *base);

/** @} end of sprite */

#endif
